import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class IPPacketFragmentation {
    private static final int MAX_PACKET_SIZE = 65535; // 最大IP数据包大小
    private static final int FRAGMENT_SIZE = 1500; // 分片大小

    public static class Packet {
        private int id;
        private int offset;
        private boolean moreFragments;
        private byte[] data;

        public Packet(int id, int offset, boolean moreFragments, byte[] data) {
            this.id = id;
            this.offset = offset;
            this.moreFragments = moreFragments;
            this.data = data;
        }
    }

    public static List<Packet> fragmentPacket(Packet packet) {
        List<Packet> fragments = new ArrayList<>();
        int totalFragments = (packet.data.length / FRAGMENT_SIZE) + 1;
        int offset = 0;

        for (int i = 0; i < totalFragments; i++) {
            int dataSize = Math.min(FRAGMENT_SIZE, packet.data.length - offset);
            byte[] fragmentData = new byte[dataSize];
            System.arraycopy(packet.data, offset, fragmentData, 0, dataSize);

            Packet fragment = new Packet(packet.id, offset / 8, (offset + dataSize) < packet.data.length, fragmentData);
            fragments.add(fragment);

            offset += dataSize;
        }

        return fragments;
    }

    public static Packet reassemblePacket(List<Packet> fragments) {
        int totalDataSize = fragments.stream().mapToInt(fragment -> fragment.data.length).sum();
        byte[] assembledData = new byte[totalDataSize];
        int offset = 0;

        for (Packet fragment : fragments) {
            System.arraycopy(fragment.data, 0, assembledData, offset, fragment.data.length);
            offset += fragment.data.length;
        }

        return new Packet(fragments.get(0).id, fragments.get(0).offset, fragments.get(fragments.size() - 1).moreFragments, assembledData);
    }

    public static void main(String[] args) {
        try {
            // 读取原始数据包
            byte[] originalData = readPacketFromFile("original_packet.bin");

            // 创建原始数据包对象
            Packet originalPacket = new Packet(12345, 0, false, originalData);

            System.out.println("Original Packet:");
            System.out.println("ID: " + originalPacket.id);
            System.out.println("Offset: " + originalPacket.offset);
            System.out.println("More fragments: " + originalPacket.moreFragments);
            System.out.println("Data: " + new String(originalPacket.data, "UTF-8") + "\n");

            // 分片原始数据包
            List<Packet> fragments = fragmentPacket(originalPacket);

            for (int i = 0; i < fragments.size(); i++) {
                Packet fragment = fragments.get(i);
                System.out.println("Fragment " + (i + 1) + "/" + fragments.size() + ":");
                System.out.println("ID: " + fragment.id);
                System.out.println("Offset: " + fragment.offset);
                System.out.println("More fragments: " + fragment.moreFragments);
                System.out.println("Data: " + new String(fragment.data, "UTF-8") + "\n");
            }

            // 重组分片
            Packet reassembledPacket = reassemblePacket(fragments);

            System.out.println("Reassembled Packet:");
            System.out.println("ID: " + reassembledPacket.id);
            System.out.println("Offset: " + reassembledPacket.offset);
            System.out.println("More fragments: " + reassembledPacket.moreFragments);
            System.out.println("Data: " + new String(reassembledPacket.data, "UTF-8"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static byte[] readPacketFromFile(String filePath) throws IOException {
        File file = new File(filePath);
        byte[] data = new byte[(int)file.length()];

        try (FileInputStream fis = new FileInputStream(file)) {
            fis.read(data);
        }

        return data;
    }
}
